package com.enjoy.jvm.hotspot.src.share.vm.classfile;

import com.enjoy.jvm.hotspot.src.share.vm.oops.InstanceKlass;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class BootClassLoader {

    public static final String SUFFIX = ".class";

    /**
     * 该类加载器的加载路径
     * 多个路径以分号分隔
     * 只有一个的话，分号可以省略
     * 注意路径后面的斜杠不可丢
     */
    private static final String searchPath = "/Users/wanghanhong/IdeaProjects/enjoy-jvm/out/production/open-jvm/";

    /**
     * 用于存储该类加载器加载的所有类
     */
    private static final Map<String, InstanceKlass> classLoaderData = new HashMap<>();

    /**
     * main函数所在的类在此保存一份引用，方便快速定位到
     */
    private static InstanceKlass mainKlass = null;

    public static void setMainKlass(InstanceKlass mainKlass) {
        BootClassLoader.mainKlass = mainKlass;
    }

    public static InstanceKlass loadKlass(String name) {
        return loadClass(name, true);
    }

    public static InstanceKlass loadClass(String name, Boolean resolve) {
        InstanceKlass klass = findLoadedKlass(name);
        if (klass != null) {
            return klass;
        }
        klass = readAndParse(name);

        if (resolve) {
            resolveClass();
        }

        return klass;
    }

    private static void resolveClass() {

    }

    /**
     * 这里写成字节数组，hotspot源码是流
     */
    private static InstanceKlass readAndParse(String name) {
        String temName = name.replace(".", "/");
        String filePath = searchPath + temName + SUFFIX;
        File file = new File(filePath);
        FileInputStream inputStream = null;
        try {
            // 读取字节码文件
            byte[] content = new byte[(int) file.length()];
            inputStream = new FileInputStream(file);
            int i = inputStream.read(content);
            System.out.println("文件大小：" + i + "字节");

            // 解析字节码
            InstanceKlass klass = ClassFileParser.parseClassFile(content);

            // 存入
            classLoaderData.put(name, klass);

            return klass;

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                assert inputStream != null;
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private static InstanceKlass findLoadedKlass(String name) {
        return classLoaderData.get(name);
    }

    /**
     * hotspot源码会去找有main方法的类，这里简单处理
     */
    public static InstanceKlass loadMainKlass(String name) {
        if (null != mainKlass) {
            return mainKlass;
        }

        return loadKlass(name);
    }
}
